# coding: utf-8

import operator
import math


def to_radians(deg: float):
    return (math.pi * deg) / 180


def to_degrees(rad: float):
    return (180 * rad) / math.pi


class vec2:
    x: float = 0.0
    y: float = 0.0

    def __init__(self, x: float = 0.0, y: float = 0.0) -> None:
        self.x = x
        self.y = y

    def __str__(self) -> str:
        return f"({self.x},{self.y})"

    def __eq__(self, other: object) -> bool:
        return operator.eq(self.x, other.x) and operator.eq(self.y, other.y)

    def __ne__(self, other: object) -> bool:
        return not (operator.eq(self.x, other.x) and operator.eq(self.y, other.y))

    def __mul__(self, other: float) -> "vec2":
        return vec2(self.x * other, self.y * other)

    def __rmul__(self, other: float) -> "vec2":
        return self * other

    def __add__(self, other: object):
        if type(other) == float or type(other) == int:
            return vec2(self.x + other, self.y + other)
        elif type(other) == vec2:
            return vec2(self.x + other.x, self.y + other.y)
        else:
            raise Exception("__add__: invalid object!")

    def __iadd__(self, other: object):
        if type(other) == float or type(other) == int:
            self.x += other
            self.y += other
            return self
        elif type(other) == vec2:
            self.x += other.x
            self.y += other.y
            return self
        else:
            raise Exception("__iadd__: invalid object!")

    def __sub__(self, other: object):
        if type(other) == float or type(other) == int:
            return vec2(self.x - other, self.y - other)
        elif type(other) == vec2:
            return vec2(self.x - other.x, self.y - other.y)
        else:
            raise Exception("__sub__: invalid object!")

    def __isub__(self, other: object):
        if type(other) == float or type(other) == int:
            self.x -= other
            self.y -= other
            return self
        elif type(other) == vec2:
            self.x -= other.x
            self.y -= other.y
            return self
        else:
            raise Exception("__isub__: invalid object!")

    def __neg__(self) -> "vec2":
        return vec2(-self.x, -self.y)

    def magnitude(self):
        return math.sqrt(self.x * self.x + self.y * self.y)

    def normalized(self):
        L = self.magnitude()
        return vec2(self.x / L, self.y / L)

    def rotate(self, deg: float):
        rad = to_radians(deg)
        sin = math.sin(rad)
        cos = math.cos(rad)
        return vec2(self.x * cos + self.y * sin, -self.x * sin + self.y * cos)

    def __truediv__(self, scalar: float) -> "vec2":
        if scalar == 0:
            raise ValueError("Cannot divide by zero.")
        return vec2(self.x / scalar, self.y / scalar)


def dot(u: vec2, v: vec2):
    return u.x * v.x + u.y * v.y


def distance(u: vec2, v: vec2):
    x = v.x - u.x
    y = v.y - u.y
    return math.sqrt(x * x + y * y)


def cross(u: vec2, v: vec2):
    return u.x * v.y - u.y * v.x


if __name__ == "__main__":
    a = vec2(3, 4)
    b = vec2(1, 5)
    # print(a, b)
    # print(a == b)
    # print(a != b)
    c = a + b
    # print(a, b, c)
    a += 10
    # print(a)
    a += b
    # print(a)
